﻿using Leo.Awesome.DictionaryManagement.Domain;
using Leo.Awesome.DictionaryManagement.Dtos;
using Leo.Awesome.DictionaryManagement.Services;
using Leo.Core.Application;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;

namespace Leo.Awesome.DictionaryManagement.Servcies
{
    public class DictionaryItemAppService : BaseCrudAppService
        <DictionaryItem,
        DictionaryItemGetOutPutDto,
        DictionaryItemGetListOutputDto,
        DictionaryItemPagedResultDto,
        Guid,
        DictionaryItemGetListInput,
        DictionaryItemCreateUpdateInput,
        DictionaryItemCreateUpdateInput,
        DictionaryItemGetListPageInput
        >, IDictionaryItemAppService
    {
        private readonly IDictionaryItemRepository mainRepository;
        private readonly ISectionRepository sectionRepository;

        public DictionaryItemAppService(IDictionaryItemRepository mainRepository,
            ISectionRepository sectionRepository) : base(mainRepository)
        {
            this.mainRepository = mainRepository;
            this.sectionRepository = sectionRepository;
        }

        public override async Task<DictionaryItemGetOutPutDto> CreateAsync(DictionaryItemCreateUpdateInput input)
        {
            await CheckDictionaryItemCreateUpdateInput(input);
            return await base.CreateAsync(input);
        }

        protected override IQueryable<DictionaryItem> BuildQuery(DictionaryItemGetListInput getListInput, IQueryable<DictionaryItem> query)
        {
            query = query.WhereIf(!getListInput.Name.IsNullOrWhiteSpace(), 
                                        x => x.Name.Contains(getListInput.Name)
                                        ||x.Name.Contains(getListInput.Code))
                          .WhereIf(getListInput.IsEnable.HasValue, 
                                x => x.IsEnabled == getListInput.IsEnable);
            query = query.OrderBy(x => x.OrderIndex);
            return base.BuildQuery(getListInput, query);
        }

        public override async Task<DictionaryItemPagedResultDto> QueryByPage(DictionaryItemGetListPageInput getListPageInput)
        {
            var output = await base.QueryByPage(getListPageInput);
            var dictionarids = output.Items.Select(x => x.DictionaryId).ToList();
            if (dictionarids.Any())
            {
                var sections = await sectionRepository.GetListAsync(x => dictionarids.Contains(x.Id));
                foreach (var item in output.Items)
                {
                    var section = sections.FirstOrDefault(x => x.Id == item.DictionaryId);
                    if (section != null)
                    {
                        item.DictionaryName = section.Name;
                    }
                }
            }
            return output;
        }
        protected override async Task<IQueryable<DictionaryItem>> CreateFilteredQueryAsync(DictionaryItemGetListInput getListInput)
        {
            var query = await ReadOnlyRepository.GetQueryableAsync();
            if (!getListInput.SectionCode.IsNullOrWhiteSpace())
            {
                var sections = await sectionRepository.GetListAsync(x => x.Code == getListInput.SectionCode);
                var sectionIds = sections.Select(x => x.Id).ToList();
                query = query.Where(x => sectionIds.Contains(x.DictionaryId));
            }
            if (!getListInput.Name.IsNullOrWhiteSpace())
            {
                query = query.Where(x => x.Name.Contains(getListInput.Name) || x.Code.Contains(getListInput.Name));
            }
            if (!getListInput.TreePath.IsNullOrEmpty())
            {
                var sections = await sectionRepository.GetListAsync(x => x.TreePath.Contains(getListInput.TreePath));
                var sectionIds = sections.Select(x => x.Id).ToList();
                query = query.Where(x => sectionIds.Contains(x.DictionaryId));
            }
            return query;
        }
        public override async Task<List<DictionaryItemGetListOutputDto>> Query(DictionaryItemGetListInput getListInput)
        {
            var output = await base.Query(getListInput);
            output = output.OrderBy(x => x.OrderIndex).ToList();
            return output;
        }

        public override async Task<DictionaryItemGetOutPutDto> UpdateAsync(Guid id, DictionaryItemCreateUpdateInput input)
        {
            await CheckDictionaryItemCreateUpdateInput(input);
            var islock = await mainRepository.AnyAsync(x => x.Id == id && x.IsLocked == true);
            CheckBusinessErrors(islock, $"该字典项【{input.Name}】已被其他地方引用,不能被编辑!");
            return await base.UpdateAsync(id, input);
        }

        public override async Task DeleteAsync(Guid id)
        {
            var islock = await mainRepository.AnyAsync(x => x.Id == id && x.IsLocked == true);
            CheckBusinessErrors(islock, $"该字典项已被其他地方引用,不能被删除!");
            await base.DeleteAsync(id);
        }

        private async Task CheckDictionaryItemCreateUpdateInput(DictionaryItemCreateUpdateInput input)
        {
            CheckBusinessErrors(input == null, "参数错误!");
            CheckBusinessErrors(input.Name.IsNullOrWhiteSpace(), "请输入名称");
            var exist = await mainRepository.AnyAsync(x => x.Code == input.Code
             && x.Id != input.Id);

            CheckBusinessErrors(exist, $"输入的编码【{input.Code}】,已经存在，请重新输入");
        }

     

    }
}
